package com.sy.musicapp.model

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sy.musicapp.Util
import com.sy.musicapp.intent.network.MusicAppNetwork
import com.sy.musicapp.service.MediaPlayerService
import com.sy.musicapp.showToast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.util.*
import kotlin.random.Random

/**
 * 音乐列表ViewModel
 * @author SY
 * @since 2022-01-22 21:37
 **/
class MusicViewModel : ViewModel(), MediaPlayerService.MusicStateListener {

    var isPlay = MutableStateFlow(false) //是否在播放
    var playMode = MutableStateFlow(PlayMode.ALL_CYCLE)
    var isLittleControlShow = MutableStateFlow(false) //是否显示小控制器
    var isMusicListShow = MutableStateFlow(false) //是否显示播放歌曲列表
    var musicList = MutableStateFlow(emptyList<Music>()) //播放列表
    var currentMusicIndex = MutableStateFlow(-1)
    var currentMusic = MutableStateFlow(Music.Empty)
    var excludeScreen = listOf(Screen.Login.route, Screen.Play.route, Screen.Splash.route)

    var currentNavName: String = Screen.Home.route //当前路由页
        set(value) {
            field = value
            isLittleControlShow.value = !excludeScreen.contains(field)
        }
    private lateinit var musicBinder: MediaPlayerService.MusicBinder
    fun setMusicBinder(binder: MediaPlayerService.MusicBinder) {
        musicBinder = binder
    }


    fun musicListShowChange() {
//        if (musicList.value.isEmpty() and !isMusicListShow.value) {
//            "列表为空".showToast()
//        } else {
        isMusicListShow.value = !isMusicListShow.value
//        }
    }

    //直接赋值传递的是地址，导致更改播放列表时原列表也会被更改
    fun addAllToMusicList(list: List<Music>) {
        musicList.value = emptyList()
        val temp = mutableListOf<Music>()
        temp.addAll(list)
        musicList.value = temp.toList()
    }

    fun addNextToMusicList(item: Music) {
        Util.showLog(item)
        val temp = item.copy() //深拷贝
        temp.isNext = true
        val tempList = musicList.value.toMutableList()
        if (tempList.isNotEmpty()) {
            tempList.add(currentMusicIndex.value + 1, temp)
        } else tempList.add(temp)
        musicList.value = tempList.toList()
        "添加成功".showToast()
    }

    fun delFromMusicList(index: Int) {
        if (index == currentMusicIndex.value) {
            musicBinder.resetState()
            currentMusic.value = Music.Empty
            currentMusicIndex.value = -1
        }
        try {
            val tempList = musicList.value.toMutableList()
            tempList.removeAt(index)
            musicList.value = tempList.toList()
        } catch (e: IndexOutOfBoundsException) {
            e.printStackTrace()
        }
    }

    fun getCurrentMusic(): Music {
        return if (musicList.value.isEmpty())
            Music.Empty
        else
            musicList.value[currentMusicIndex.value]
    }

    fun start(index: Int) {
        viewModelScope.launch(Dispatchers.Main) {
            try {
                val playMusic = musicList.value[index]
                currentMusicIndex.emit(index)
                currentMusic.emit(playMusic)
                if (playMusic.url.isNullOrBlank()) {
                    MusicAppNetwork.getMusicDetail(playMusic.id).body()?.let { music ->
                        musicBinder.start(music.url, this@MusicViewModel)
                        playMusic.url = music.url
                        playMusic.br = music.br
                        playMusic.fee = music.fee
                        playMusic.size = music.size
                        playMusic.type = music.type
                    }
                } else {
                    musicBinder.start(playMusic.url, this@MusicViewModel)
                }
            } catch (e: Exception) {
                "start失败".showToast()
                e.printStackTrace()
            }
        }
    }

    override fun completed(isPrev: Boolean) {
        var num: Int = currentMusicIndex.value
        val completeMusic = musicList.value.getOrNull(num)
        if (completeMusic != null) {
            if (completeMusic.isNext) {
                val tempList = musicList.value.toMutableList()
                tempList.removeAt(num)
                musicList.value = tempList.toList()
                start(num)
                return
            }
        }
        when (playMode.value) {
            PlayMode.ALL_CYCLE -> {
                //全部循环
                num = if (isPrev)
                    currentMusicIndex.value - 1
                else
                    currentMusicIndex.value + 1
            }
            PlayMode.RANDOM_PLAY -> {
                //随机播放
                num = Random.nextInt(0, musicList.value.size - 1)
            }
            else -> {
                /**单曲循环不会执行动作*/
            }
        }
        num = when (num) {
            in 0..musicList.value.size -> num
            else -> 0
        }
        start(num)
    }


    fun playStateChange() {
        if (musicBinder.isPlaying()) musicBinder.pause()
        else {
            musicBinder.play()
        }
        isPlay.value = musicBinder.isPlaying()
    }


    fun jumpTotime(time: Int) {
        musicBinder.seekTo(time)
    }

    override fun prepared() {
        isPlay.value = musicBinder.isPlaying()
        currentMusic.value.duration = musicBinder.getDuration()
        viewModelScope.launch(Dispatchers.Main) {
            try {
                MusicAppNetwork.getLyric(currentMusic.value.id).body()?.let {
                    currentMusic.value.lyric = convertLyric(it)
                }
            } catch (e: Exception) {
                e.printStackTrace()
                "请求歌词失败".showToast()
                val str =
                    "[00:04.050]\n[00:12.570]难以忘记初次见你\n[00:16.860]一双迷人的眼睛\n[00:21.460]在我脑海里\n[00:23.960]你的身影 挥散不去\n[00:30.160]握你的双手感觉你的温柔\n[00:34.940]真的有点透不过气\n[00:39.680]你的天真 我想珍惜\n[00:43.880]看到你受委屈 我会伤心\n[00:48.180]喔\n[00:50.340]只怕我自己会爱上你\n[00:55.070]不敢让自己靠的太近\n[00:59.550]怕我没什么能够给你\n[01:04.030]爱你也需要很大的勇气\n[01:08.190]只怕我自己会爱上你\n[01:12.910]也许有天会情不自禁\n[01:17.380]想念只让自己苦了自己\n[01:21.840]爱上你是我情非得已\n[01:28.810]难以忘记初次见你\n[01:33.170]一双迷人的眼睛\n[01:37.700]在我脑海里 你的身影 挥散不去\n[01:46.360]握你的双手感觉你的温柔\n[01:51.120]真的有点透不过气\n[01:55.910]你的天真 我想珍惜\n[02:00.150]看到你受委屈 我会伤心\n[02:04.490]喔\n[02:06.540]只怕我自己会爱上你\n[02:11.240]不敢让自己靠的太近\n[02:15.750]怕我没什么能够给你\n[02:20.200]爱你也需要很大的勇气\n[02:24.570]只怕我自己会爱上你\n[02:29.230]也许有天会情不自禁\n[02:33.680]想念只让自己苦了自己\n[02:38.140]爱上你是我情非得已\n[03:04.060]什么原因 耶\n[03:07.730]我竟然又会遇见你\n[03:13.020]我真的真的不愿意\n[03:16.630]就这样陷入爱的陷阱\n[03:20.700]喔\n[03:22.910]只怕我自己会爱上你\n[03:27.570]不敢让自己靠的太近\n[03:32.040]怕我没什么能够给你\n[03:36.560]爱你也需要很大的勇气\n[03:40.740]只怕我自己会爱上你\n[03:45.460]也许有天会情不自禁\n[03:49.990]想念只让自己苦了自己\n[03:54.510]爱上你是我情非得已\n[03:58.970]爱上你是我情非得已\n[04:03.000]\n"
                currentMusic.value.lyric = convertLyric(str)

            }
        }
    }


    fun convertLyric(str: String): List<Lyric> {
        val arrs = str.split("\n")
        val temp = mutableListOf<Lyric>()
        for (arr in arrs) {
            val obj = arr.split("]")
            val timeStr = obj[0].removePrefix("[")
            if (timeStr.isBlank()) continue
            val time = timeStr.split(Regex("[:.]"))
            val result = converToMilliseconds(time[0], time[1], time[2])
            temp.add(Lyric(result, obj[1]))
        }
        return temp.toList()
    }

    /**
     * 将以字符串形式给定的分钟、秒钟、毫秒转换成毫秒
     * @param min 分钟
     * @param sec 秒钟
     * @param mill 毫秒
     * @return Int
     */
    private fun converToMilliseconds(min: String?, sec: String?, mill: String?): Int {
        // 转成整型
        val m = Integer.parseInt(min ?: "0");
        val s = Integer.parseInt(sec ?: "0");
        val ms = Integer.parseInt(mill ?: "0");
        // 组合成一个长整型表示的以毫秒为单位的时间
        val time = m * 60 * 1000 + s * 1000 + ms;
        return time;
    }


    /**
     * 更换播放模式
     * 单曲循环 → 全部循环 → 随机播放 → 单曲循环
     */
    fun changeMode() {
        when (playMode.value) {
            PlayMode.SINGLE_CYCLE -> {
                musicBinder.setLoop(true)
                playMode.value = PlayMode.ALL_CYCLE
            }
            PlayMode.ALL_CYCLE -> {
                musicBinder.setLoop(false)
                playMode.value = PlayMode.RANDOM_PLAY
            }
            PlayMode.RANDOM_PLAY -> {
                musicBinder.setLoop(false)
                playMode.value = PlayMode.SINGLE_CYCLE
            }

        }
    }

    fun getCurrentProgress(): Int {
        return musicBinder.getCurrent()
    }

    fun resetAll(){
        isPlay = MutableStateFlow(false) //是否在播放
        playMode = MutableStateFlow(PlayMode.ALL_CYCLE)
        isMusicListShow = MutableStateFlow(false) //是否显示播放歌曲列表
        musicList = MutableStateFlow(emptyList()) //播放列表
        currentMusicIndex = MutableStateFlow(-1)
        currentMusic = MutableStateFlow(Music.Empty)
    }


    override fun onError(msg: String) {
        try {
            Util.showLog(currentMusic.value.toString())
            msg.showToast()
            Thread.sleep(1000)
            completed()
        } catch (e: Exception) {
            e.printStackTrace()
            "onError Exception".showToast()
            Util.showLog("onError Exception")
        }
    }
}